home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / PROGEDIT / H402.ZIP / ELV17SRC.ZIP / UNIX.C < prev    next >
C/C++ Source or Header  |  1992-12-30  |  5KB  |  223 lines

  1. /* unix.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains the unix-specific versions the ttyread() functions.
  12.  * There are actually three versions of ttyread() defined here, because
  13.  * BSD, SysV, and V7 all need quite different implementations.
  14.  */
  15.  
  16. #include "config.h"
  17. #if ANY_UNIX
  18. # include "vi.h"
  19.  
  20. # if BSD
  21. /* For BSD, we use select() to wait for characters to become available,
  22.  * and then do a read() to actually get the characters.  We also try to
  23.  * handle SIGWINCH -- if the signal arrives during the select() call, then
  24.  * we adjust the o_columns and o_lines variables, and fake a control-L.
  25.  */
  26. #  include <sys/types.h>
  27. #  include <sys/time.h>
  28. int ttyread(buf, len, time)
  29.     char    *buf;    /* where to store the gotten characters */
  30.     int    len;    /* maximum number of characters to read */
  31.     int    time;    /* maximum time to allow for reading */
  32. {
  33.     fd_set    rd;    /* the file descriptors that we want to read from */
  34.     static    tty;    /* 'y' if reading from tty, or 'n' if not a tty */
  35.     int    i;
  36.     struct timeval t;
  37.     struct timeval *tp;
  38.  
  39.  
  40.     /* do we know whether this is a tty or not? */
  41.     if (!tty)
  42.     {
  43.         tty = (isatty(0) ? 'y' : 'n');
  44.     }
  45.  
  46.     /* compute the timeout value */
  47.     if (time)
  48.     {
  49.         t.tv_sec = time / 10;
  50.         t.tv_usec = (time % 10) * 100000L;
  51.         tp = &t;
  52.     }
  53.     else
  54.     {
  55.         tp = (struct timeval *)0;
  56.     }
  57.  
  58.     /* loop until we get characters or a definite EOF */
  59.     for (;;)
  60.     {
  61.         if (tty == 'y')
  62.         {
  63.             /* wait until timeout or characters are available */
  64.             FD_ZERO(&rd);
  65.             FD_SET(0, &rd);
  66.             i = select(1, &rd, (fd_set *)0, (fd_set *)0, tp);
  67.         }
  68.         else
  69.         {
  70.             /* if reading from a file or pipe, never timeout!
  71.              * (This also affects the way that EOF is detected)
  72.              */
  73.             i = 1;
  74.         }
  75.     
  76.         /* react accordingly... */
  77.         switch (i)
  78.         {
  79.           case -1:    /* assume we got an EINTR because of SIGWINCH */
  80.             if (*o_lines != LINES || *o_columns != COLS)
  81.             {
  82. #ifndef CRUNCH
  83.                 *o_nearscroll = 
  84. #endif
  85.                 *o_lines = LINES;
  86.                 *o_columns = COLS;
  87. #ifndef CRUNCH
  88.                 if (!wset)
  89.                 {
  90.                     *o_window = LINES - 1;
  91.                 }
  92. #endif
  93.                 if (mode != MODE_EX)
  94.                 {
  95.                     /* pretend the user hit ^L */
  96.                     *buf = ctrl('L');
  97.                     return 1;
  98.                 }
  99.             }
  100.             break;
  101.     
  102.           case 0:    /* timeout */
  103.             return 0;
  104.     
  105.           default:    /* characters available */
  106.             return read(0, buf, len);
  107.         }
  108.     }
  109. }
  110. # else
  111.  
  112. # if UNIXV || COH_386
  113. /* For System-V, we use VMIN/VTIME to implement the timeout.  For no timeout,
  114.  * VMIN should be 1 and VTIME should be 0; for timeout, VMIN should be 0 and
  115.  * VTIME should be the timeout value.
  116.  */
  117. #  include <termio.h>
  118. int ttyread(buf, len, time)
  119.     char    *buf;    /* where to store the gotten characters */
  120.     int    len;    /* maximum number of characters to read */
  121.     int    time;    /* maximum time to allow for reading */
  122. {
  123.     struct termio tio;
  124.     int    bytes;    /* number of bytes actually read */
  125.  
  126.     /* arrange for timeout */
  127.     ioctl(0, TCGETA, &tio);
  128.     if (time)
  129.     {
  130.         tio.c_cc[VMIN] = 0;
  131.         tio.c_cc[VTIME] = time;
  132.     }
  133.     else
  134.     {
  135.         tio.c_cc[VMIN] = 1;
  136.         tio.c_cc[VTIME] = 0;
  137.     }
  138.     ioctl(0, TCSETA, &tio);
  139.  
  140.     /* Perform the read.  Loop if EINTR error happens */
  141.     while ((bytes = read(0, buf, (unsigned)len)) < 0)
  142.     {
  143.         /* probably EINTR error because a SIGWINCH was received */
  144.         if (*o_lines != LINES || *o_columns != COLS)
  145.         {
  146.             *o_lines = LINES;
  147.             *o_columns = COLS;
  148. #ifndef CRUNCH
  149.             if (!wset)
  150.             {
  151.                 *o_nearscroll = LINES;
  152.                 *o_window = LINES - 1;
  153.             }
  154. #endif
  155.             if (mode != MODE_EX)
  156.             {
  157.                 /* pretend the user hit ^L */
  158.                 *buf = ctrl('L');
  159.                 return 1;
  160.             }
  161.         }
  162.     }
  163.  
  164.     /* return the number of bytes read */
  165.     return bytes;
  166.  
  167.     /* NOTE: The terminal may be left in a timeout-mode after this function
  168.      * returns.  This shouldn't be a problem since Elvis *NEVER* tries to
  169.      * read from the keyboard except through this function.
  170.      */
  171. }
  172.  
  173. # else /* any other version of UNIX, assume it is V7 compatible */
  174.  
  175. /* For V7 UNIX (including Minix) we set an alarm() before doing a blocking
  176.  * read(), and assume that the SIGALRM signal will cause the read() function
  177.  * to give up.
  178.  */
  179.  
  180. #include <setjmp.h>
  181.  
  182. static jmp_buf env;
  183.  
  184. /*ARGSUSED*/
  185. SIGTYPE dummy(signo)
  186.     int    signo;
  187. {
  188.     longjmp(env, 1);
  189. }
  190. int ttyread(buf, len, time)
  191.     char    *buf;    /* where to store the gotten characters */
  192.     int    len;    /* maximum number of characters to read */
  193.     int    time;    /* maximum time to allow for reading */
  194. {
  195.     /* arrange for timeout */
  196.     signal(SIGALRM, dummy);
  197.     alarm(time);
  198.  
  199.     /* perform the blocking read */
  200.     if (setjmp(env) == 0)
  201.     {
  202.         len = read(0, buf, (unsigned)len);
  203.     }
  204.     else /* I guess we timed out */
  205.     {
  206.         len = 0;
  207.     }
  208.  
  209.     /* cancel the alarm */
  210.     signal(SIGALRM, dummy); /* <-- to work around a bug in Minix */
  211.     alarm(0);
  212.  
  213.     /* return the number of bytes read */
  214.     if (len < 0)
  215.         len = 0;
  216.     return len;
  217. }
  218.  
  219. # endif /* M_SYSV */
  220. # endif /* !BSD */
  221.  
  222. #endif /* ANY_UNIX */
  223.